home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / ASTRONOM / H139.ZIP / RO101.ZIP / RO_MACR.C < prev    next >
C/C++ Source or Header  |  1991-11-04  |  15KB  |  644 lines

  1. /********************************************************/
  2. /*                            */
  3. /*    ro_macr.c    macro and diversion routines    */
  4. /*            for ro                */
  5. /*                            */
  6. /*    ro version 1.10                    */
  7. /*                            */
  8. /*    Portions copyright (c) 1989 by Ted A. Campbell    */
  9. /*        Bywater Software            */
  10. /*        P. O. Box 4023                */
  11. /*        Duke Station                */
  12. /*        Durham, NC  27706            */
  13. /*                            */
  14. /*    Contains portions of ROFF4, Version 1.60    */
  15. /*      (c) 1983, 4 by Ernest E. Bergmann               */
  16. /*        Physics, Building #16            */
  17. /*        Lehigh University            */
  18. /*        Bethlehem, Pa. 18015            */
  19. /*                            */
  20. /*    Contains portions of ROFF4, Version 1.61    */
  21. /*      (c) 1985 by Konrad Kwok                         */
  22. /*        20 3rd Street, Section M        */
  23. /*        Fariview Park,                */
  24. /*        Hong Kong                */
  25. /*                            */
  26. /*    ro and its predecessor ROFF4 are based on     */
  27. /*    the ROFF text processor described in Kernigan    */
  28. /*    and Plauger's now-classic text <Software Tools> */
  29. /*                            */
  30. /* Permission is hereby granted for all commercial and    */
  31. /* non-commercial reproduction and distribution of this */
  32. /* material provided this notice is included.        */
  33. /*                            */
  34. /********************************************************/
  35.  
  36. #include "ro.h"
  37.  
  38. /********************************************/
  39. /* insert()  -- process .ds command        */
  40. /* takes a command line in ro_curline and adds its
  41. entry to the table */
  42.  
  43. insert()
  44.    {
  45.    static char name[ LSZ ];
  46.    register int n;
  47.    char c, *l;
  48.    struct divfd *sptr;
  49.  
  50.     /*pass over command*/
  51.  
  52.     l = ro_curline;
  53.     for ( c = *l; c != ' ' && c != '\n' && c != '\t'; l++ )
  54.       {
  55.       c = *l;
  56.       }
  57.  
  58.     /*advance to first non-blank */
  59.  
  60.     for ( ; c == ' ' || c == '\t'; l++ )
  61.       {
  62.       c = *l;
  63.       }
  64.     if ( c == '\n' )
  65.       {
  66.       if ( ro_verbose == TRUE )
  67.          {
  68.          fprintf( stderr, ".ds:  no arguments \n" );
  69.          }
  70.       return -1;
  71.       }
  72.  
  73.    /* get the name of the macro into the buffer */
  74.  
  75.    n = 0;
  76.    --l;
  77.    do
  78.       {
  79.       name[ n ] = *l;
  80.       ++l;
  81.       ++n;
  82.       }
  83.    while( *l != ' ' && *l != '\t' && *l != '\n' );
  84.    name[ n ] = '\0';      /* terminate name with \0 */
  85.  
  86.    if ( strlen( name ) > 2 ) 
  87.       {
  88.       name[ 2 ] = '\0';
  89.       if ( ro_verbose == TRUE )
  90.          {
  91.          fprintf( stderr, ".ds:  string name over two characters, shortened to <%s>. \n", 
  92.             name );
  93.          }
  94.       }
  95.  
  96.      /*advance to first non-blank */
  97.  
  98.     c = *l;
  99.     for ( ; c == ' ' || c == '\t'; l++ )
  100.       {
  101.       c = *l;
  102.       }
  103.     if ( c == '\n' )
  104.       {
  105.       if ( ro_verbose == TRUE )
  106.          {
  107.          fprintf( stderr, ".ds:  no string argument \n" );
  108.          }
  109.       return -1;
  110.       }
  111.  
  112.    /* now get the string itself into the tbuf buffer */
  113.  
  114.    if (( c == '\"' ) || ( c == '\'' ))
  115.       {
  116.       n = 0;
  117.       do
  118.          {
  119.          tbuf[ n ] = *l;
  120.          ++l;
  121.          ++n;
  122.          }
  123.       while( *l != c );
  124.       tbuf[ n ] = '\0';      /* terminate name with \0 */
  125.       }
  126.    else
  127.       {
  128.       n = 0;
  129.       do
  130.          {
  131.          tbuf[ n ] = *l;
  132.          ++l;
  133.          ++n;
  134.          }
  135.       while( *l != ' ' && *l != '\t' && *l != '\n' );
  136.       tbuf[ n ] = '\0';      /* terminate name with \0 */
  137.       }
  138.  
  139.    /* see if it is already defined     */
  140.  
  141.    if( ( sptr = find2( name, slink )) != NULL )   
  142.       {
  143.       if ( ro_verbose == TRUE )
  144.          {
  145.          fprintf( stderr, "%cWarning: <%s> was defined to be <%s>\n",
  146. /*            BELL, name, sptr->mstr );
  147.    brachet@imag.imag.fr      05/17/90
  148. */
  149.             BELL, name, (sptr->mstr ? sptr->mstr : "" ));
  150.          fprintf( stderr, "...now it is defined to be <%s>\n", tbuf );
  151.          }
  152.       }
  153.  
  154.    else 
  155.       {
  156.       if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
  157.          {
  158.          fprintf( stderr, "Fatal error: cannot allocate memory for insertion structure.  \n" ); 
  159.          exit ( -1 );
  160.          }
  161.  
  162.       /* allocation succeeded, set up links */
  163.  
  164.       sptr->prev = slink;      /* save previous link   */
  165.       slink = sptr;         /* reset link      */
  166.       strcpy( sptr->nm, name );
  167.       sptr->mstr = NULL;
  168.       }
  169.  
  170.    /* allocate memory for the new string if it is longer 
  171.       than the current string */ 
  172.  
  173.    if ( sptr->mstr == NULL || strlen( tbuf ) > strlen( sptr->mstr ) )
  174.       {
  175.       if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
  176.          {
  177.          fprintf( stderr, "Fatal error:  failed to allocate memory for string. \n" );
  178.          exit( -1 );
  179.          }
  180.       }
  181.  
  182.    /* copy the string to the new memory */
  183.  
  184.    strcpy( sptr->mstr, tbuf );
  185.  
  186.    }
  187.  
  188. /****************************************/
  189.  
  190. showit()      /* displays the list of entries in the string
  191.          substitution table pointed to by HEAD. */
  192.    {
  193.    struct divfd *pw;
  194.    fprintf( stderr, "Strings defined:\n");
  195.    dashes();
  196.    pw = slink;
  197.    while( pw != NULL )
  198.       {
  199.       fprintf( stderr, "%s:\t<%s> \n", pw->nm, pw->mstr );
  200.       pw = pw->prev;
  201.       }
  202.    dashes();
  203.    }
  204.  
  205. /****************************************/
  206.  
  207. putback( c )   /*cf K & P, p256*/
  208.    char c;
  209.    {
  210.    if ( ++ro_binp >= BACKSIZE )
  211.       {
  212.       fprintf( stderr, "Fatal error:  too many characters pushed back\n");
  213.       exit( -1 );
  214.       }
  215.    ro_backbuf[ ro_binp ] = c;
  216.    }
  217.  
  218. /** add by Conrad Kwok. 9th Sept.,84 ****/
  219.  
  220. pbmac( s, sl )         /* s = pointer to macro text    */
  221.    char s[], sl[];      /* sl = current line       */
  222.    {
  223.    static char *parms[10], dupln[LSZ];
  224.    register int i;
  225.  
  226.    strcpy( dupln, sl );      /* get a copy of the current line */
  227.    setparm( dupln, parms );
  228.    for ( i = strlen(s)-1; i >= 0; )
  229.       {
  230.       if ( isdigit( s[i] ))
  231.          {
  232.          if ( i > 0 && s[ i - 1 ] == '$' )
  233.             { 
  234.             pbstr( parms[ s[i--] & 0x0f ]); 
  235.             --i;
  236.             }
  237.          else
  238.             {
  239.             putback( s[i--] );
  240.             }
  241.          }
  242.       else
  243.          {
  244.          putback( s[i--] );
  245.          }
  246.       }
  247.    }
  248.  
  249. setparm( sl, parms)
  250.    char *sl, *parms[];
  251.    { 
  252.    char a,c;
  253.    int nuparm;
  254.    for ( c = *sl; c != ' ' && c != '\n' && c != '\t'; )
  255.       {
  256.       c = *++sl;
  257.       }
  258.  
  259.    while ( c == ' ' || c == '\t' )
  260.       {
  261.       c = *++sl;
  262.       }
  263.  
  264.    for ( nuparm = 0; nuparm < 10; ) 
  265.       {
  266.       if (!(isalnum(c) || (c=='+') || (c=='-')))
  267.          {
  268.          sl++;
  269.          }
  270.       else
  271.          {
  272.          c = ' ';
  273.          }
  274.       parms[ nuparm++ ] = sl;
  275.  
  276.       for ( a = *sl; a != c && a != '\n' && a != '\0'; )
  277.          {
  278.          if ( c == ' ' && a == '\t' ) 
  279.             {
  280.             break;
  281.             }
  282.  
  283.          else 
  284.             {
  285.             a = *++sl;
  286.             }
  287.          }
  288.       *sl = '\0';
  289.       c = a;
  290.       if ( a != '\0' && a != '\n') 
  291.          {
  292.          while ( c == ' ' || c == '\t') 
  293.             {
  294.             c = *++sl;
  295.             }
  296.          }
  297.       }
  298.    }
  299.  
  300. /****************************************/
  301.  
  302. pbstr( s )      /*put back string on input; cf K&P,p257*/
  303.    char s[LSZ];
  304.    {
  305.    int i;
  306.    for ( i = strlen(s); i > 0; ) 
  307.       {
  308.       putback( s[--i] );
  309.       }
  310.    }
  311.  
  312. /****************************************************************
  313.  
  314.    ro_expand()   Expand a macro
  315.  
  316. ****************************************************************/
  317.  
  318. ro_expand()
  319.    {
  320.    char c, d, name[ 36 ];
  321.    register int n;
  322.    struct divfd *sptr;
  323.  
  324.    c = ro_getch();
  325.    switch( c )
  326.       {
  327.       case BACKSLASH:
  328.          return PASSBACK;   /* pass literal backslash
  329.                      through the system */
  330.          break;
  331.       case '*':         /* expand defined string */
  332.          d = ro_getch();
  333.          if ( d == '(' )   /* two-letter name */
  334.             {
  335.             name[ 0 ] = ro_getch();
  336.             name[ 1 ] = ro_getch();
  337.             name[ 2 ] = '\0';
  338.             }
  339.          else      /* one-character name */
  340.             {
  341.             name[ 0 ] = d;
  342.             name[ 1 ] = '\0';
  343.             }
  344.          if ( ( sptr = find2( name, slink )) == NULL )
  345.             {
  346.             if ( ro_verbose == TRUE )
  347.                {
  348.                fprintf( stderr, "ro:  failed to find string name <%s> \n", 
  349.                   name );
  350.                }
  351.             }
  352.          else
  353.             {
  354. /*            n = strlen( sptr->mstr ) - 1;
  355.    brachet@imag.imag.fr      05/17/90
  356. */
  357.             n = (sptr->mstr ? strlen( sptr->mstr ) - 1 : 0 );
  358.             while( n >= 0 )
  359.                {
  360.                putback( sptr->mstr[ n ] );
  361.                --n;
  362.                }
  363.             }
  364.          break;
  365.       case 'n':      /* expand number register */
  366.          d = ro_getch();
  367.          if ( d == '(' )   /* two-letter name */
  368.             {
  369.             name[ 0 ] = ro_getch();
  370.             name[ 1 ] = ro_getch();
  371.             name[ 2 ] = '\0';
  372.             }
  373.          else      /* one-character name */
  374.             {
  375.             name[ 0 ] = d;
  376.             name[ 1 ] = '\0';
  377.             }
  378.          if ( ( sptr = find2( name, rlink )) == NULL )
  379.             {
  380.             if ( ro_verbose == TRUE )
  381.                {
  382.                fprintf( stderr, "ro:  failed to find register name <%s> \n", 
  383.                   name );
  384.                }
  385.             }
  386.          else
  387.             {
  388.             sprintf( tbuf, "%d", sptr->val );
  389.             n = strlen( tbuf ) - 1;
  390.             while( n >= 0 )
  391.                {
  392.                putback( tbuf[ n ] );
  393.                --n;
  394.                }
  395.             }
  396.          break;
  397.       case 'u':      /* Half-line up */
  398.          putback( HALFUP );
  399.          putback( ESCAPE );
  400.          break;
  401.       case 'd':      /* Half-line down */
  402.          putback( HALFDOWN );
  403.          putback( ESCAPE );
  404.          break;
  405.       case 'f':      /* switch font */
  406.          d = ro_getch();
  407.          switch( d )
  408.             {
  409.             case 'R':
  410.                putback( ROMAN );
  411.                putback( ESCAPE );
  412.                break;
  413.             case 'I':
  414.                putback( ITALIC );
  415.                putback( ESCAPE );
  416.                break;
  417.             case 'B':
  418.                putback( BOLD );
  419.                putback( ESCAPE );
  420.                break;
  421.             default: 
  422.                if ( ro_verbose == TRUE )
  423.                   {
  424.                   fprintf( stderr, 
  425.                      "ro:  unrecognized font name \"%c\" in input stream. \n", 
  426.                      d );
  427.                   }
  428.             }
  429.          break;
  430.       default:
  431.          putback( c );
  432.          break;
  433.       }
  434.    return TRUE;
  435.    }
  436.  
  437. /****************************************/
  438. /* takes a .de and following lines and places
  439. the information in the table;   no macro
  440. definition nesting permitted */
  441.  
  442. minsert()
  443.    {
  444.    register int n;
  445.    static char c, *src, *dst;
  446.    int keepon;
  447.    struct divfd *sptr;
  448.  
  449. #ifdef   DEBUG
  450.    if ( ro_debug == TRUE )
  451.       {
  452.       fprintf( stderr, "DEBUG:  enter minsert() \n" );
  453.       }
  454. #endif
  455.  
  456.    /* pass over command and following white space */
  457.  
  458.    for ( src = ro_curline, c = *src; (c != ' ' ) && (c!='\n') && (c!='\t'); src++ )
  459.       {
  460.       c = *src;
  461.       }
  462.    for ( ; (c == ' ') || (c == '\t'); src++ ) 
  463.       {
  464.       c = *src;
  465.       }
  466.  
  467.    /* Check to see if there is a name for the macro */
  468.  
  469.    if ( ( c == '\n' ) || ( c == '\0' ))
  470.       {
  471.       if ( ro_verbose )
  472.          {
  473.          fprintf( stderr, "ERROR:  .de:  no name given. \n");
  474.          }
  475.       return -1;
  476.       }
  477.  
  478.    /* Name detected, proceed to store the name */
  479.  
  480.    else
  481.       {
  482. #ifdef   DEBUG
  483.       if ( ro_debug == TRUE )
  484.          {
  485.          fprintf( stderr, "DEBUG:  macro name found; prepare to allocate memory. \n" );
  486.          }
  487. #endif
  488.  
  489.       if ( ( sptr = (struct divfd *) malloc( (size_t) sizeof( struct divfd ))) == NULL )
  490.          {
  491.          fprintf( stderr, "FATAL ERROR: cannot allocate memory for macro definition structure.  \n" );
  492.          exit ( -1 );
  493.          }
  494.  
  495. #ifdef   DEBUG
  496.       if ( ro_debug == TRUE )
  497.          {
  498.          fprintf( stderr, "DEBUG:  memory allocated for macro.\n" );
  499.          }
  500. #endif
  501.  
  502.       sptr->prev = mlink;             /* save previous link   */
  503.       mlink = sptr;         /* set mlink to this   */
  504.       n = 0;
  505.       while( class( c ) == BLACK )   /* Store each character */
  506.          {         /* of the macro name    */
  507.          sptr->nm[ n++ ] = c;
  508.          c = *( src++ );
  509.          }
  510.       sptr->nm[ n ] = '\0';
  511.  
  512. #ifdef   DEBUG
  513.       if ( ro_debug == TRUE )
  514.          {
  515.          fprintf( stderr, "DEBUG:  new macro name is <%s> \n",
  516.             sptr->nm );
  517.          }
  518. #endif
  519.  
  520.       }
  521.  
  522.    /* Now read from instream until end of macro or EOF */
  523.  
  524.    dst = tbuf;
  525.    keepon = 1;
  526.    while( keepon == 1 )
  527.       {
  528.       ro_gets( ro_curline );
  529.       src = ro_curline;
  530.  
  531.       /* Check for end of macro */
  532.  
  533.       if (( ro_curline[0] == COMMAND) && ( comtyp( ro_curline ) == EM ))
  534.          {
  535.          keepon = 0;
  536.          }
  537.       else         /* Not end; transfer to buffer   */
  538.          {
  539.          transfer( &src, &dst, (char) '\0' );
  540.          *(dst - 1) = '\n';   /* put a LF at the end    */
  541.          *dst = 0;      /* and a temp. delimiter */
  542.          }
  543.  
  544. #ifdef   DEBUG
  545.       if ( ro_debug == TRUE )
  546.          {
  547.          fprintf( stderr, "DEBUG:  minsert() current line <%s> \n", 
  548.             tbuf );
  549.          }
  550. #endif
  551.  
  552.       }
  553.    *( dst ) = '\0';                /* Terminate with \0            */
  554.  
  555. #ifdef   DEBUG
  556.    if ( ro_debug == TRUE )
  557.       {
  558.       fprintf( stderr, "DEBUG:  text of new macro is <%s> \n", tbuf );
  559.       }
  560. #endif
  561.  
  562.    /* allocate memory for this macro string and transfer the string to
  563.       the new location */ 
  564.  
  565.    if ( ( sptr->mstr = malloc( (size_t) strlen( tbuf ) + 1 )) == NULL )
  566.       {
  567.       fprintf( stderr, "Fatal error:  failed to allocate memory for macro string. \n" );
  568.       exit( -1 );
  569.       }
  570.    strcpy( sptr->mstr, tbuf );
  571.  
  572.    }
  573.  
  574. /****************************************/
  575.  
  576. showm() /*lists macro definitions*/
  577.    {
  578.    struct divfd *pw;
  579.    fprintf( stderr, "MACROS DEFINED:\n");
  580.    pw = mlink;
  581.    while ( pw != NULL )
  582.       {
  583.       fprintf( stderr, "\t.%s\t<%s>\n", pw->nm, pw->mstr );
  584.       pw = pw->prev;
  585.       }
  586.    dashes();
  587.    }
  588.  
  589. /****************************************/
  590.  
  591. char *macq( line )              /*looks up name to see if it is a macro
  592.             definition.   If it is, returns the
  593.             corresponding string, else returns
  594.             FALSE.
  595.             */
  596.    char *line;
  597.    {
  598.    char c, *pc, wb[ LSZ ];
  599.    struct divfd *pstr;
  600.  
  601.    pc = wb;
  602.    while ( class( c = *( ++line )) == BLACK )
  603.       {
  604.       *( pc++ ) = c;
  605.       }
  606.    *pc='\0';
  607.  
  608.    pstr = find2( wb, mlink );
  609.    if ( pstr == NULL )
  610.       {
  611.       return NULL;
  612.       }
  613.    else
  614.       {
  615.       return ( pstr->mstr );
  616.       }
  617.    }
  618.  
  619. /****************************************/
  620.  
  621. struct divfd *
  622. find2( s, link)       /* finds or doesn't find s in table
  623.              of substitutions pointed to by link */
  624.    char *s;
  625.    struct divfd *link;
  626.    {
  627.    struct divfd *l;
  628.  
  629.    l = link;
  630.    while ( l != NULL )
  631.       {
  632.       if ( !strcmp( s, l->nm ) )
  633.          {
  634.          return( l );    /* return structure pointer     */
  635.          }
  636.       l = l->prev;
  637.       }
  638.  
  639.    return( NULL );            /* failed      */
  640.    }
  641.  
  642. /****************************************/
  643.  
  644.